package com.example.demo.controller;

import com.example.demo.entity.PdfPageField;
import com.example.demo.entity.RequestVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceCharacteristicsDictionary;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDTextField;
import org.apache.pdfbox.pdmodel.interactive.form.PDVariableText;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.util.Matrix;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

@Slf4j
@RestController
@RequestMapping(value = "/pdf")
public final class CreateSimpleForm {
    public static final String DEFAULT_FILENAME = "C:\\Users\\Administrator\\Desktop\\SimpleForm.pdf";
    public static final String DEFAULT_FILENAME2 = "C:\\Users\\Administrator\\Desktop\\SimpleForm2.pdf";

    private CreateSimpleForm() {
        Queue<Integer> queue = new LinkedList<>();
    }

    @RequestMapping(value = "/createTemplate", method = RequestMethod.POST)
    public boolean createTemplate(@RequestBody RequestVo requestVo) throws IOException {
        create(requestVo);
        return true;
    }

    private static void create(RequestVo requestVo) throws IOException {

        if (requestVo.getFields() == null) {
            return;
        }

        // Create a new document with an empty page.
        try {
            File file = new File(DEFAULT_FILENAME);
            PDDocument document = PDDocument.load(file);
            float multiple = requestVo.getMultiple();
            List<PdfPageField> fields = requestVo.getFields();
            for (int i = 0; i < fields.size(); i++) {
                PdfPageField pageField = fields.get(i);
                PDPage page = document.getPage(pageField.getPage() - 1);

                if (!pageField.getType().equals("seal")) {
                    // 添加新的页面
//                PDPage page = new PDPage(PDRectangle.A4);
//                document.addPage(page);

                    // Adobe Acrobat uses Helvetica as a default font and
                    // stores that under the name '/Helv' in the resources dictionary
//                PDFont font = PDType1Font.HELVETICA;

//                String fontPath = "/WenQuanZhengHei-1.ttf";
//                InputStream resourceAsStream = OpenTypeScript.class.getResourceAsStream(fontPath);
//                PDType0Font font = PDType0Font.load(document, resourceAsStream);
                    // 设置方块中文字字体
                    PDFont font = PDType0Font.load(document, new File("C:\\Windows\\Fonts\\simhei.ttf"));
                    PDResources resources = new PDResources();
                    COSName fontName = resources.add(font);
//                    resources.put(COSName.getPDFName("Helv"), font);


                    // Add a new AcroForm and add that to the document
                    PDAcroForm acroForm = new PDAcroForm(document);
                    document.getDocumentCatalog().setAcroForm(acroForm);
                    // Add and set the resources and default appearance at the form level
                    acroForm.setDefaultResources(resources);
                    String da = "/" + fontName.getName() + " 0 Tf 0 g";
                    acroForm.setDefaultAppearance(da);

                    // Acrobat sets the font size on the form level to be
                    // auto sized as default. This is done by setting the font size to '0'
//                String defaultAppearanceString = "/Helv 0 Tf 0 g";
//                acroForm.setDefaultAppearance(defaultAppearanceString);

                    // Add a form field to the form.
                    PDTextField textBox = new PDTextField(acroForm);
                    // 设置方块变量
                    textBox.setPartialName(pageField.getName());

                    // Acrobat sets the font size to 12 as default
                    // This is done by setting the font size to '12' on the
                    // field level.
                    // The text color is set to blue in this example.
                    // To use black, replace "0 0 1 rg" with "0 0 0 rg" or "0 g".
//                defaultAppearanceString = "/Helv 12 Tf 0 0 1 rg";
//                textBox.setDefaultAppearance(defaultAppearanceString);

                    // add the field to the acroform
                    acroForm.getFields().add(textBox);
                    // Specify the widget annotation associated with the field
                    PDAnnotationWidget widget = textBox.getWidgets().get(0);

                    // 设置方块的位置
                    log.info(pageField.getX() + " : " + pageField.getY());
                    log.info(page.getMediaBox().getWidth() + " : " + page.getMediaBox().getHeight());
                    float y = page.getMediaBox().getHeight() - pageField.getY() / multiple - pageField.getHeight() / multiple;
                    PDRectangle rect = new PDRectangle(pageField.getX() / multiple, y,
                            pageField.getWidth() / multiple, pageField.getHeight() / multiple);
                    widget.setRectangle(rect);
                    widget.setPage(page);
                    // set green border and yellow background
                    // if you prefer defaults, delete this code block
                    PDAppearanceCharacteristicsDictionary fieldAppearance
                            = new PDAppearanceCharacteristicsDictionary(new COSDictionary());
                    // 设置边框颜色
                    fieldAppearance.setBorderColour(new PDColor(new float[]{0, 0, 0}, PDDeviceRGB.INSTANCE));
                    // 设置背景色
                    fieldAppearance.setBackground(new PDColor(new float[]{70, 130, 180}, PDDeviceRGB.INSTANCE));
                    widget.setAppearanceCharacteristics(fieldAppearance);
                    // make sure the widget annotation is visible on screen and paper
                    widget.setPrinted(false);

                    // Add the widget annotation to the page
                    page.getAnnotations().add(widget);
                    // 设置方块上文字位置
                    textBox.setQ(PDVariableText.QUADDING_CENTERED);
                    // 设置方块上显示文字
                    textBox.setValue(pageField.getName());
                    // 设置方块不可编辑
                    textBox.setReadOnly(true);
                } else {
                    // 在 pdf 文档中追加图片
                    PDImageXObject pdImage = PDImageXObject.createFromFile(
                            "C:\\Users\\Administrator\\Desktop\\sign.jpg", document);
                    // 使用在原文档基础上，追加图片的方式
                    PDPageContentStream contentStream = new PDPageContentStream(document, page,
                            PDPageContentStream.AppendMode.APPEND, false, false);
                    float y = page.getMediaBox().getHeight() - pageField.getY() / multiple - pageField.getHeight() / multiple;
                    contentStream.drawImage(pdImage, pageField.getX() / multiple, y, pageField.getWidth() / multiple, pageField.getHeight() / multiple);
                    contentStream.close();
                }
            }
            // 保存文档
            if (fields != null && fields.size() > 0) {
                document.save(DEFAULT_FILENAME2);
            }
            document.close();
        } catch (Exception ex) {
            log.error("生成合同模板文件出错", ex);
        }
    }

    @RequestMapping(value = "/getImage", method = RequestMethod.GET)
    public void getImage(@RequestParam("pageNo") int pageNo, HttpServletResponse response) throws IOException {

        File file = new File(DEFAULT_FILENAME);
        PDDocument document = PDDocument.load(file);
        PDFRenderer renderer = new PDFRenderer(document);
        // pdf 转换为图片，并增加像素点数
        BufferedImage bufferedImage = renderer.renderImageWithDPI(pageNo - 1, 256);
        File imageFile = new File("C:\\Users\\Administrator\\Desktop\\test.png");
        ImageIO.write(bufferedImage, "png", imageFile);
        FileInputStream inputStream = new FileInputStream(imageFile);
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=" + imageFile.getName());
        OutputStream outputStream = response.getOutputStream();
        int len = 0;
        byte[] by = new byte[1024 * 10];
        while ((len = inputStream.read(by)) > 0) {
            outputStream.write(by, 0, len);
        }
        outputStream.close();
        inputStream.close();
        /*HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_JPEG);
        byte[] bytes = FileUtils.readFileToByteArray(imageFile);*/
        document.close();
//        return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
    }

    @RequestMapping(value = "/getPageCount", method = RequestMethod.GET)
    public int getPageCount() throws IOException {
        int pageCount = 0;
        File file = new File(DEFAULT_FILENAME);
        PDDocument document = PDDocument.load(file);
        pageCount = document.getPages().getCount();
        document.close();
        return pageCount;
    }

    @RequestMapping(value = "/addWaterMark", method = RequestMethod.GET)
    public boolean addWaterMark() throws IOException {
        File file = new File(DEFAULT_FILENAME);
        PDDocument document = PDDocument.load(file);
        for (PDPage everyPage : document.getPages()) {
            PDPageContentStream cs = new PDPageContentStream(document, everyPage, PDPageContentStream.AppendMode.APPEND,
                    true, true);
            String ts = "水印测试";
            float fontSize = 80.0f;
            PDExtendedGraphicsState r0 = new PDExtendedGraphicsState();
            // 透明度
            r0.setNonStrokingAlphaConstant(0.3f);
            r0.setAlphaSourceFlag(true);

            cs.setGraphicsStateParameters(r0);
            cs.setNonStrokingColor(188, 188, 188);
            cs.beginText();
            PDFont font = PDType0Font.load(document, new File("C:\\Windows\\Fonts\\simhei.ttf"));
            cs.setFont(font, fontSize);
            // 获取旋转实例
            cs.setTextMatrix(Matrix.getRotateInstance(45, 100f, 200f));
            cs.showText(ts);
            cs.endText();

            cs.close();
        }
        document.save(DEFAULT_FILENAME2);
        document.close();
        return true;
    }

}
